import yaml
import pytest
from common.cache import cache
from common.exceptions import YamlException,RequestException
from common.httprequest import HttpRequest
from common.result import check_results, get_result
from utils.logger import logger


def pytest_collect_file(parent, path):
    if path.ext in (".yaml", ".yml") and path.basename.startswith("test"):
        return YamlFile.from_parent(parent, fspath=path)


class YamlFile(pytest.File):

    def collect(self):
        raw = yaml.safe_load(self.fspath.open(encoding='utf-8'))
        if not any(k.startswith('test') for k in raw.keys()):
            raise YamlException("{}yaml non test found".format(self.fspath))
        variable = raw.get('variable')
        if variable:
        # if variable := raw.get('variable'):
            for k, v in variable.items():
                cache.set(k, v)
        config = raw.get('config')
        if config:
        # if config := raw.get('config'):
            for k, v in config.items():
                cache.set(k, v)
        tests = raw.get('tests')
        if tests:
        # if tests := raw.get('tests'):
            for name, spec in tests.items():
                yield YamlTest.from_parent(self,
                                           name=spec.get(
                                               'description') or name,
                                           spec=spec)

class YamlTest(pytest.Item):
    def __init__(self, name, parent, spec):
        super(YamlTest, self).__init__(name, parent)
        self.spec = spec
        self.request = HttpRequest(exception=(RequestException, Exception))

    def repr_failure(self, excinfo):
        """Called when self.runtest() raises an exception."""
        logger.critical(excinfo.value)
        logger.critical(excinfo.traceback[-6:-1])

    def reportinfo(self):
        return self.fspath, 0, f"usecase: {self.name}"

    def runtest(self):
        """Some custom test execution (dumb example follows)."""
        r = self.request.send_request(**self.spec)
        self.response_handle(r, self.spec.get('Validate'), self.spec.get('Extract'))

    def response_handle(self, r, validate, extract):
        """Handling of responses"""
        if validate:
            check_results(r, validate)
        if extract:
            get_result(r, extract)